设计模式(六)命令模式 & 观察者模式

  1. 命令模式
    1. 应用场景
    2. 总结
  2. 观察者模式
    1. 应用场景
    2. 方案一
    3. 方案二
    4. 方案三
    5. 总结

命令模式

应用场景

使用多功能的遥控器打开一个电灯

public interface Command {
    public void execute();
}

public class LightOnCommand implements Command {
    Light light;

    public LigitOnCommand(Light light) {
        this.light = light;
    }

    public void execute() {
        light.on();
    }
}

public class SimpleRemoteControl {
    Command slot;

    public SimpleRemoteControl() { }

    public void setCommand(Command command) {
        slot = command;
    }

    public void buttonWasPressed() {
        slot.execute();
    }
}

public class RemoteControlTest {
    public static void main(String[] args) {
        SimpleRemoteControl remote = new SimpleRemoteControl();
        Light light = new Light();
        LightOnCommand lightOn = new LightOnCommand(light);

        remote.setCommand(lightOn);
        remote.buttonWasPressed();
    }
}

遥控器是调用者,电灯是接收者。创建一个命令并将接收者传给命令,然后将命令传给调用者。这样,将发出请求的对象和执行请求的对象解耦,通过命令对象沟通。

一个命令对象通过在特定接收者上绑定一组动作来封装一个请求,其它对象不知道究竟哪个接收者进行了哪些动作,只知道调用execute方法,请求的目的就能达到。

总结

命令模式将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其它对象,命令模式也支持可撤销的操作。

观察者模式

应用场景

气象站将数据传输到显示装置上显示

方案一

错误的示范

public class WeatherData1 {
    public void measurementsChanged() {
        float temp = getTemperature();
        float pressure = getPressure();

        displayer1.update(temp, pressure);
        displayer2.update(temp, pressure);
    }
}

这样就耦合了具体的对象displayer1和displayer2了

方案二

应用观察者

public interface Subject {
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObservers();
}

public interface Observer {
    public void update(float temp, float pressure);
}

public interface DisplayElement {
    public void display();
}

public class WeatherData2 implements Subject {
    private ArrayList observers;
    private float temperature;
    private float pressure;

    public WeatherData() {
        observers = new ArrayList();
    }

    public void registerObserver(Observer o) {
        observers.add(o);
    }

    public void removeObserver(Observer o) {
        int i = observers.indexOf(o);
        if (i >=0) {
            observers.remove(i);
        }
    }

    public void notifyObservers() {
        for (int i = 0; i < observers.size(); i++) {
            Observer observer = (Observer)observers.get(i);
            observer.update(temperature, pressure);
        }
    }

    public void measurementsChanged() {
        notifyObservers();
    }

    public void setMeasurements(float temperature, float pressure) {
        this.temperature = temperature;
        this.pressure = pressure;
        measurementsChanged();
    }
}

public class Displayer1 implements Observer, DisplayElement {
    private float temperature;
    private Subject weatherData;

    public Displayer1(Subject weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

    public void update(float temperature, float pressure) {
        this.temperature = temperature;
        display();
    }

    public void display() {
        //... 显示的实现
    }
}

方案三

还可以利用系统内置观察方式实现

import java.util.Observable;
import java.util.Observer;

public class WeatherData3 implements Observable {
    private float temperature;
    private float pressure;

    public WeatherData() { } //不再需要记住观察者的数据结构

    public void measurementsChanged() {
        setChanged(); //通知观察者前先标记状态改变了(系统API)
        notifyObservers(); //通知观察者(系统API)
    }

    public void setMeasurements(float temperature, float pressure) {
        this.temperature = temperature;
        this.pressure = pressure;
        measurementsChanged();
    }
}

public class Displayer2 implements Observer, DisplayElement {
    private float temperature;
    Observable observable;

    public Displayer1(Observable observable) {
        this.observable = observable;
        observable.addObserver(this);
    }

    public void update(Observer obs, Object arg) {
        if (obs instanceof WeatherData3) {
            WeatherData3 weatherData = (WeatherData3)obs;
            this.temperature = weatherData.getTemperature();
            display();
        }
    }

    public void display() {
        //... 显示的实现
    }
}

可见系统内置的观察方式,已经帮我们定义了注册观察者、通知观察者及其触发的更新方法。只是特别需要注意setChanged()这个方法需要在状态改变后先调用,后再调用notifyObservers()。

总结

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 mingfungliu@gmail.com

文章标题:设计模式(六)命令模式 & 观察者模式

文章字数:847

本文作者:Mingfung

发布时间:2019-02-12, 14:28:00

最后更新:2019-02-12, 14:34:39

原始链接:http://blog.ifungfay.com/设计模式/设计模式(六)命令模式 & 观察者模式/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏

宝贝回家